package nx.simple3d.data;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class ObjFile implements GeometryProvider{
  
  private BufferedReader reader;
  private List<Double> vertices = new ArrayList<Double>();
  private List<Double> textureCoords = new ArrayList<Double>();
  private List<Double> normals = new ArrayList<Double>();
  
  private List<Integer> indicesVertices = new ArrayList<Integer>();
  private List<Integer> indicesTextureCoords = new ArrayList<Integer>();
  private List<Integer> indicesNormals = new ArrayList<Integer>();
  
  private double[] verticesArray;
  private int[] indicesVerticesArray;
  
  public ObjFile(File file) throws FileNotFoundException{
    FileInputStream fis = new FileInputStream(file);
    reader = new BufferedReader(new InputStreamReader(fis));
    
    try {
      initialize();
    }
    catch (IOException e) {
      e.printStackTrace();
    }
  }
  
  private void initialize() throws IOException{
    String line;
    String[] tokens;
    String[] vtnTokens;
    int faceVertices;
    
    while((line = reader.readLine()) != null){
      tokens = line.split("[\\s]+");
      if(tokens[0].equalsIgnoreCase("v")){
        vertices.add(Double.parseDouble(tokens[1]));
        vertices.add(Double.parseDouble(tokens[2]));
        vertices.add(Double.parseDouble(tokens[3]));
      }
      else if(tokens[0].equalsIgnoreCase("vt")){
        //textureCoords.add(Double.parseDouble(tokens[1]));
        //textureCoords.add(Double.parseDouble(tokens[2]));
      }
      else if(tokens[0].equalsIgnoreCase("vn")){
        normals.add(Double.parseDouble(tokens[1]));
        normals.add(Double.parseDouble(tokens[2]));
        normals.add(Double.parseDouble(tokens[3]));
      }
      else if(tokens[0].equalsIgnoreCase("f")){
        faceVertices = 0;
        for(int i = 1; i < tokens.length; i++){          
          vtnTokens = tokens[i].split("[/]");
          indicesVertices.add(Integer.parseInt(vtnTokens[0]) - 1);
          if(vtnTokens.length > 1){
            if(!vtnTokens[1].equals(""))
              indicesTextureCoords.add(Integer.parseInt(vtnTokens[1]) - 1);
            if(vtnTokens.length > 2)
              indicesNormals.add(Integer.parseInt(vtnTokens[2]) - 1);
          }
        }
      }
    }
  }
  
  public int getVertexCount(){
    return vertices.size() / 3;
  }
  
  public int getNormalCount(){
    return vertices.size() / 3;
  }
  
  public void writeVerticesTo(VectorBase vb, int startIndex){
    for(int i = 0; i < vertices.size() / 3; i+=3){
      vb.x[startIndex + i / 3 + 0] = vertices.get(i + 0);
      vb.y[startIndex + i / 3 + 1] = vertices.get(i + 1);
      vb.z[startIndex + i / 3 + 2] = vertices.get(i + 2);
    }
  }
  
  public void writeNormalsTo(VectorBase vb, int startIndex){
    for(int i = 0; i < normals.size() / 3; i+=3){
      vb.x[startIndex + i / 3] = normals.get(i + 0);
      vb.y[startIndex + i / 3] = normals.get(i + 1);
      vb.z[startIndex + i / 3] = normals.get(i + 2);
    }
  }
  
  public Mesh createMesh(){    
    return new Mesh(this);
  }

  @Override
  public double[] getVertices() {
    if(verticesArray == null){
      verticesArray = new double[vertices.size()];
      for(int i = 0; i < verticesArray.length; i++)
        verticesArray[i] = vertices.get(i);
    }
    return verticesArray;
  }

  @Override
  public int[] getIndicesVertices() {
    if(indicesVerticesArray == null){
      indicesVerticesArray = new int[indicesVertices.size()];
      for(int i = 0; i < indicesVerticesArray.length; i++)
        indicesVerticesArray[i] = indicesVertices.get(i);
    }
    return indicesVerticesArray;
  }
}
  
